import os
import random
import json # 引入 json 库
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import dashscope
from dashscope import Generation
from http import HTTPStatus
from dotenv import load_dotenv

# --- 配置 ---
load_dotenv()
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
if not dashscope.api_key:
    print("错误：未找到 DASHSCOPE_API_KEY 环境变量。")

# --- 初始化 FastAPI 应用 ---
app = FastAPI(
    title="个性化教育 AI 服务 (V2 - 支持动态出题)",
    description="提供错题解析、题目推荐、动态出题功能",
    version="2.0.0"
)

# --- 数据模型 ---

class ExplanationRequest(BaseModel):
    question_content: str
    question_options: str | None = None
    correct_answer: str
    student_answer: str

class ExplanationResponse(BaseModel):
    explanation: str

class RecommendationRequest(BaseModel):
    student_id: int
    knowledge_mastery_map: dict
    count: int

class RecommendationResponse(BaseModel):
    recommended_question_ids: list[int]

# --- 新增: 动态出题的数据模型 ---
class DynamicQuestionRequest(BaseModel):
    knowledge_point_name: str
    subject: str = "数学"
    question_type: str = "SINGLE_CHOICE"
    difficulty: float = 0.5

class DynamicQuestionResponse(BaseModel):
    content: str
    options: str # 必须是 JSON 字符串
    answer: str # 必须是 JSON 字符串
    analysis: str
    difficulty: float

# --- API 端点 ---

@app.get("/", tags=["通用"])
def read_root():
    return {"message": "AI 服务已启动 (V2 - 通义千问版)"}

@app.post("/ai/explanation", response_model=ExplanationResponse, tags=["AI 辅导"])
def get_ai_explanation(request: ExplanationRequest):
    # ... (此部分代码保持不变) ...
    if not dashscope.api_key:
        raise HTTPException(status_code=500, detail="服务器未配置 Dashscope API Key")
    prompt = f"""
    你是一位经验丰富、耐心友善的数学老师。请根据以下信息，为一位学生提供清晰、鼓励性的错题解析。
    **题目信息:**
    - 题目内容: {request.question_content}
    - 题目选项: {request.question_options if request.question_options else "无"}
    - 正确答案: {request.correct_answer}
    **学生作答情况:**
    - 学生的答案: {request.student_answer}
    **你的任务:**
    请按照以下结构生成解析：
    1.  **肯定与鼓励**: 先用一句话肯定学生付出的努力。
    2.  **知识点定位**: 指出这道题考察的核心知识点是什么。
    3.  **思路对比**: 清晰地分析学生的答案可能错误的原因，并与正确解题思路进行对比。请不要直接说“你错了”，而是用引导性的语言。
    4.  **举一反三 (可选)**: 如果可能，给出一个类似但更简单的例子来巩固知识点。
    5.  **总结与鼓励**: 最后用一句话鼓励学生继续努力。
    请使用中文回答，语言要通俗易懂。

    另外格式要求:严格遵守MardDown格式，不允许出现$ a $这种带空格的情况，以及各种不规范的公式

    """
    try:
        response = Generation.call(model='qwen-turbo', messages=[{'role': 'system', 'content': '你是一位经验丰富、耐心友善的数学老师。'}, {'role': 'user', 'content': prompt}], result_format='message')
        if response.status_code == HTTPStatus.OK:
            return ExplanationResponse(explanation=response.output.choices[0]['message']['content'])
        else:
            print(f"调用通义千问API失败: Code={response.code}, Message={response.message}")
            raise HTTPException(status_code=503, detail="AI 服务暂时不可用")
    except Exception as e:
        print(f"调用 Dashscope API 时发生未知错误: {e}")
        raise HTTPException(status_code=500, detail="处理AI请求时发生内部错误。")


@app.post("/recommend/questions", response_model=RecommendationResponse, tags=["个性化推荐"])
def get_recommendations(request: RecommendationRequest):
    # ... (此占位符端点保持不变) ...
    print(f"收到学生 {request.student_id} 的推荐请求，请求数量: {request.count}")
    print(f"学生能力图谱: {request.knowledge_mastery_map}")
    random_ids = random.sample(range(1, 101), request.count)
    return RecommendationResponse(recommended_question_ids=random_ids)


# --- 新增: AI 动态出题端点 ---
@app.post("/ai/generate-question", response_model=DynamicQuestionResponse, tags=["AI 出题"])
def generate_dynamic_question(request: DynamicQuestionRequest):
    """
    根据指定的知识点，动态生成一道新题目。
    """
    if not dashscope.api_key:
        raise HTTPException(status_code=500, detail="服务器未配置 Dashscope API Key")

    prompt = f"""
    你是一位资深的{request.subject}出题专家。请根据以下要求，生成一道全新的题目。

    **出题要求:**
    - **核心知识点**: {request.knowledge_point_name}
    - **题目类型**: {request.question_type}
    - FILL_IN_BLANK: 填空题
    - **目标难度系数**: {request.difficulty} (0.0代表最简单，1.0代表最难)
    - **生成的题目不要重复**
    - **对于填空题或选择题，填写位置不要用___，使用(_)来代替**
    - **不允许使用换行符，仅能使用正常文本换行**

    **输出格式要求:**
    你必须严格按照以下格式的纯 JSON 对象进行输出，不要在 JSON 对象之外添加任何额外的解释、说明或 markdown 标记。
    {{
      "content": "题目的文本内容，例如：函数 f(x) = x^3 在 x=2 处的导数是多少？",
      "options": "{{\"A\":\"6\",\"B\":\"8\",\"C\":\"12\",\"D\":\"9\"}}",
      "answer": "{{\"correct\":\"C\"}}",
      "analysis": "对这道题的详细解析。首先根据求导公式 (x^n)' = n*x^(n-1)，我们得到 f'(x) = 3x^2。然后将 x=2 代入，得到 f'(2) = 3 * (2^2) = 12。",
      "difficulty": {request.difficulty}
    }}

   **请用如下形式写公式:**

   - 用 `$f'(x) = 2x$` 表示导数，不使用 `’`（右单引号）。
   - 不要在公式中使用中文符号或非ASCII符号。
   另外格式要求:严格遵守MardDown格式，不允许出现$ a $这种带空格的情况，以及各种不规范的公式

    **特别说明:**
    - `options` 和 `answer` 字段的值必须是合法的、内部用双引号的 JSON 字符串。
    - 对于非选择题，`options` 可以是 `null`。
    - 确保整个输出是一个可以被直接解析的 JSON 对象。
    """

    try:
        response = Generation.call(
            model='qwen-plus', # 使用能力更强的模型出题
            prompt=prompt,
            result_format='text' # 获取纯文本结果以便我们自己解析JSON
        )

        if response.status_code == HTTPStatus.OK:
            # 尝试解析 AI 返回的 JSON 字符串
            try:
                # AI 可能返回被 markdown 包裹的 JSON，需要提取
                raw_text = response.output.text
                if "```json" in raw_text:
                    json_text = raw_text.split("```json")[1].split("```")[0].strip()
                else:
                    json_text = raw_text.strip()
                
                q_data = json.loads(json_text)
                return DynamicQuestionResponse(**q_data)
            except (json.JSONDecodeError, IndexError) as e:
                print(f"AI返回的JSON格式错误: {e}, 原始文本: {response.output.text}")
                raise HTTPException(status_code=500, detail="AI生成题目格式错误，无法解析")
        else:
            print(f"调用通义千问API失败: Code={response.code}, Message={response.message}")
            raise HTTPException(status_code=503, detail="AI服务暂时不可用")

    except Exception as e:
        print(f"调用Dashscope API时发生未知错误: {e}")
        raise HTTPException(status_code=500, detail="处理AI请求时发生内部错误")


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)